package com.sie.zhq.module;

import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

import com.sie.zhq.bean.TradeLogBean;
import com.sie.zhq.constconfig.ErrorDefine;
import com.sie.zhq.tool.ByteTool;
import com.sie.zhq.tool.StringUtil;
import com.sie.zhq.tool.Timer;
import com.bankcomm.peripheral.BankCardInfoBean;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by zhq on 2016/8/19.
 */
public class FinancialThread extends Thread {
    private DeviceCallback callback;
    private int timeOutMs;
    private boolean isOnMain;

    private int type;
    public static final String TAG = FinancialThread.class.getSimpleName();
    public static FinancialModule financialModule = FinancialModule.getInstance();
    public static final int READ_MSR = 1;
    public static final int READ_IC_CARD_NO = 2;
    public static final int READ_PIC_CARD_NO = 3;
    public static final int AUTO_READ_CARD_NO = 4;
    public static final int READ_IC_INFO = 5;
    public static final int READ_PIC_INFO = 6;
    public static final int AUTO_READ_CARD_INFO =9;


    public static final int READ_PIC_LOG = 7;
    public static final int READ_IC_LOG = 8;


    private boolean runFlag = true;

    public boolean isRunFlag() {
        return runFlag;
    }

    public void stopRun() {
        this.runFlag = false;
    }

    private boolean isFinish = false;

    public boolean isFinish() {

        return isFinish;
    }

    public FinancialThread(int type, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
    }


    @Override
    public void run() {
        synchronized (this) {

            switch (type) {
                case READ_MSR:
                    readMsr();
                    break;
                case READ_IC_CARD_NO:
                    readIcCardNo();
                    break;
                case READ_PIC_CARD_NO:
                    readPiccCardNo();
                    break;
                case AUTO_READ_CARD_NO:
                    autoReadCardNo();
                    break;
                case READ_IC_INFO:
                    readIcCardInfo();
                    break;
                case READ_PIC_INFO:
                    readPiccInfo();
                    break;
                case READ_IC_LOG:
                    readIcLog();
                    break;
                case READ_PIC_LOG:
                    readPicLog();
                    break;
                case AUTO_READ_CARD_INFO:
                    autoReadCardInfo();
                    break;
            }
            isFinish = true;
            Log.e(TAG, "COMPLETED");
        }
    }
    /**
     * 自动识别卡类型
     */
    public void autoReadCardInfo() {

        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            SystemClock.sleep(150);
            if (financialModule.libIccCheck((byte) 0x00) == 0) {
                if (transBeforeOnline((byte) 0x00) == 0) {

                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (transBeforeOnline((byte) 0x02) == 0) {

                    break;
                }
            }
            SystemClock.sleep(150);
            if (financialModule.libMcrCheck() == 0) {
                if (mcrRead()) {

                    financialModule.libMcrClose();
                    break;
                }
            }
            SystemClock.sleep(150);

        }
//        closeModule();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public void readPicLog() {
        Timer tm = openPicc();
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (getLog((byte) 0x02) == 0) {

                    break;
                }
            }
            SystemClock.sleep(500);
        }
        financialModule.libPiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);


    }

    public void readIcLog() {
        Timer tm = openIc();

        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            if (financialModule.libIccCheck((byte) 0x00) == 0) {

                if (getLog((byte) 0x00) == 0) {


                    break;
                }

            }
            SystemClock.sleep(500);
        }
        financialModule.libIccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);


    }

    public int getLog(int cardType) {
        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        if (financialModule.setDateTime(ByteTool.hexStr2Bytes(time)) != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.SET_TIME_ERR);
            bundle.putString("message", "SET_TIME_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return -1;
        }
//        if (financialModule.EmvLib_Init() != 0) {
//            Bundle bundle = new Bundle();
//            bundle.putInt("code", ErrorDefine.EMV_INIT_ERR);
//            bundle.putString("message", "EmvLib_Init error!");
//            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
//            return -11;
//        }
        if (setEMVParam() != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.SET_EMVPARAM_ERR);
            bundle.putString("message", "SET_EMVPARAM_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return -2;
        }
//        if (AddApp() != 0) {
//            Bundle bundle = new Bundle();
//            bundle.putInt("code", ErrorDefine.ADD_APP_ERR);
//            bundle.putString("message", "ADD_APP_ERR!");
//            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
//            return -3;
//        }
        byte[] tlog = new byte[1024];
        int[] num = new int[1];
        int res = -1;
        if (cardType == 0x00) {
            res = financialModule.EmvLib_GetLog((byte) 0x00, tlog, num);

        } else if (cardType == 0x02) {

            res = financialModule.EmvLib_GetLog((byte) 0x01, tlog, num);

        }
        Log.e("EmvLib_GetLog:", res + "--");
        List<TradeLogBean> list = parseLog(tlog);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        return res;
    }

    public void readPiccInfo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (transBeforeOnline((byte) 0x02) == 0) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        //  financialModule.libPiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public void readIcCardInfo() {
        Timer tm = openIc();

        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            if (financialModule.libIccCheck((byte) 0x00) == 0) {

                if (transBeforeOnline((byte) 0x00) == 0) {


                    break;
                }

            }
            SystemClock.sleep(500);
        }
        //financialModule.libIccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    public int transBeforeOnline(int cardType) {

        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        if (financialModule.setDateTime(ByteTool.hexStr2Bytes(time)) != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.SET_TIME_ERR);
            bundle.putString("message", "SET_TIME_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return -1;
        }
//        if (financialModule.EmvLib_Init() != 0) {
//            Bundle bundle = new Bundle();
//            bundle.putInt("code", ErrorDefine.EMV_INIT_ERR);
//            bundle.putString("message", "EmvLib_Init error!");
//            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
//            return -11;
//        }
        if (setEMVParam() != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.SET_EMVPARAM_ERR);
            bundle.putString("message", "SET_EMVPARAM_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return -2;
        }

//        if (AddApp() != 0) {
//            Bundle bundle = new Bundle();
//            bundle.putInt("code", ErrorDefine.ADD_APP_ERR);
//            bundle.putString("message", "ADD_APP_ERR!");
//            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
//            return -3;
//        }
        int TransNo = 1;
        int authorizedAmount = 0;
        int cashBack = 0;
        ret = financialModule.EmvLib_CoreGetAmt(authorizedAmount, cashBack);
        if (ret != 0) {
            Log.e(TAG, "EmvLib_CoreGetAmt: ret = " + ret);
            return -7;
        }
        int[] Num = new int[1];
        byte[] AidList = new byte[180];
        if (cardType == 0x00) {
            try {
                ret = financialModule.EmvLib_CreatAppList((byte) 0x00, (byte) 0x00, AidList, Num);
            } catch (ArrayIndexOutOfBoundsException e) {
                Log.e(TAG, "EmvLib_CreatAppList:" + e.getMessage());
                return -4;
            }
        } else if (cardType == 0x02) {
            ret = financialModule.EmvLib_qPBOCPreProcess();
            if (ret != 0) {
                Log.e(TAG, "EmvLib_qPBOCPreProcess: ret = " + ret);
                return -12;
            }
            try {
                ret = financialModule.EmvLib_CreatAppList((byte) 0x01, (byte) 0x00, AidList, Num);
            } catch (ArrayIndexOutOfBoundsException e) {
                Log.e(TAG, "EmvLib_CreatAppList:" + e.getMessage());
                return -4;
            }
        }
        Log.e("num:", Num[0] + "!!");
        if (ret != 0) {
            Log.e(TAG, "EmvLib_CreatAppList: ret = " + ret);
            return -5;
        }
        if (cardType == 0x00) {
            financialModule.EmvLib_SetSelectApp((byte) 0);
        }
        byte[] ifGoOnline = new byte[1];
        byte[] ifNeedPin = new byte[1];
        if (cardType == 0x00) {
            ret = financialModule.EmvLib_ProcTransBeforeOnline((byte) 0x00, TransNo, ifGoOnline, ifNeedPin);
            if (ret != 0) {
                Log.e(TAG, "EmvLib_ProcTransBeforeOnline: ret = " + ret);
                return -8;
            }
        } else if (cardType == 0x02) {

            ret = financialModule.EmvLib_ProcCLTransBeforeOnline((byte) 0x01, TransNo, ifGoOnline, ifNeedPin);
            if (ret != 0) {
                Log.e(TAG, "EmvLib_ProcCLTransBeforeOnline: ret = " + ret);
                return -13;
            }
        }


        String[] wantTags = {"5A", "57", "9F26", "9F27", "9F10", "9F37", "9F36",
                "95", "9A", "9C", "9F02", "5F2A", "82", "9F1A", "9F03",
                "9F33", "9F34", "9F35", "9F1E", "4F", "5F34"};

        int[] len = new int[1];
        byte[] dataOut = new byte[2048];
        ret = financialModule.EmvLib_GetTags(wantTags, dataOut, len);
        if (ret != 0) {
            Log.v(TAG, "EmvLib_GetTags: ret = " + ret);
            return -9;
        }
        byte[] out = new byte[len[0]];
        System.arraycopy(dataOut, 0, out, 0, len[0]);
        String returnstring = ByteTool.byte2hex(out);
        Log.e("string:", returnstring);

        int len5A = StringUtil.getTagLen(0, "5A", returnstring);
        String tag57 = StringUtil.tagParse(len5A * 2 + 4,
                "57", returnstring);
        Log.e("57", tag57 + "---");

        BankCardInfoBean bean = new BankCardInfoBean();

        bean.setCardType(cardType);

        bean.setCardNo(getCardNo(tag57));
        bean.setICChipData(returnstring);
        Bundle bundle = new Bundle();
        bundle.putParcelable("data", bean);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;

    }

    public int AddApp() {

        byte[] AppName = new byte[33];
        byte AidLen = 0;
        byte SelFlag = 0;
        byte Priority = 0;
        byte TargetPer = 0;
        byte MaxTargetPer = 0;
        byte FloorLimitCheck = 1;
        byte RandTransSel = 1;
        byte VelocityCheck = 1;
        int FloorLimit = 2000;
        int Threshold = 0;
        byte[] TACDenial = new byte[6];
        byte[] TACOnline = new byte[6];
        byte[] TACDefault = new byte[6];
        byte[] AcquierId = new byte[7];
        byte[] dDOL = new byte[256];
        byte[] tDOL = new byte[256];
        byte[] Version = new byte[3];
        byte[] RiskManData = new byte[10];

        byte CL_bStatusCheck = 0;
        int CL_FloorLimit = 0;
        int CL_TransLimit = 0;
        int CL_CVMLimit = 0;
        byte TermQuali_byte2 = 0;


        byte[] TACDenial_1 = {(byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00};
        byte[] TACOnline_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x04, (byte) 0xF8, (byte) 0x00};
        byte[] TACDefault_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x00, (byte) 0xA8, (byte) 0x00};
        byte[] AcquierId_1 = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x12, (byte) 0x34, (byte) 0x56};
        byte[] dDOL_1 = {(byte) 0x03, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] tDOL_1 = {(byte) 0x0F, (byte) 0x9F, (byte) 0x02, (byte) 0x06, (byte) 0x5F, (byte) 0x2A, (byte) 0x02, (byte) 0x9A, (byte) 0x03, (byte) 0x9C, (byte) 0x01, (byte) 0x95, (byte) 0x05, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] Version_1 = {(byte) 0x00, (byte) 0x8c};

        System.arraycopy(TACDenial_1, 0, TACDenial, 0, TACDenial_1.length);
        System.arraycopy(TACOnline_1, 0, TACOnline, 0, TACOnline_1.length);
        System.arraycopy(TACDefault_1, 0, TACDefault, 0, TACDefault_1.length);
        System.arraycopy(AcquierId_1, 0, AcquierId, 0, AcquierId_1.length);
        System.arraycopy(dDOL_1, 0, dDOL, 0, dDOL_1.length);
        System.arraycopy(tDOL_1, 0, tDOL, 0, tDOL_1.length);
        System.arraycopy(Version_1, 0, Version, 0, Version_1.length);

        byte[] AID1 = {(byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x33, (byte) 0x01, (byte) 0x1};
        byte[] AID = new byte[17];
        System.arraycopy(AID1, 0, AID, 0, AID1.length);
        AidLen = 7;
        FloorLimitCheck = 1;

        byte[] Version1 = new byte[3];
        byte[] Version2 = {(byte) 0x00, (byte) 0x30};
        System.arraycopy(Version2, 0, Version1, 0, Version2.length);
        byte EC_bTermLimitCheck = 1;
        int EC_TermLimit = 100000;

        EMVAPPLIST PBOC_TEST_APP = new EMVAPPLIST(AppName, AID, AidLen, SelFlag,
                Priority, TargetPer, MaxTargetPer,
                FloorLimitCheck, RandTransSel, VelocityCheck,
                FloorLimit, Threshold, TACDenial,
                TACOnline, TACDefault, AcquierId, dDOL,
                tDOL, Version1, RiskManData, EC_bTermLimitCheck,
                EC_TermLimit, CL_bStatusCheck, CL_FloorLimit, CL_TransLimit,
                CL_CVMLimit, TermQuali_byte2);


        return financialModule.EmvLib_AddApp(PBOC_TEST_APP.toBytes());

    }

    /**
     * 设置EMV
     *
     * @return
     */
    public int setEMVParam() {

        EMVParam emvParam = new EMVParam();
        byte[] MerchCateCode = new byte[2];
        MerchCateCode[0] = 0x00;
        MerchCateCode[1] = 0x01;
        emvParam.setMerchCateCode(MerchCateCode);
        String MerchId = "123456789012345";
        emvParam.setMerchId(MerchId.getBytes());
        emvParam.setMerchName("EMV LIBRARY".getBytes());
        emvParam.setTermId("12345678".getBytes());
        emvParam.setTerminalType((byte) 0x22);
        emvParam.setSurportPSESel((byte) 0x01);
        byte[] Capability = {(byte) 0xE0, (byte) 0xC0, (byte) 0xC8};
        emvParam.setCapability(Capability);
        byte[] ExCapability = {(byte) 0x60, (byte) 0x00, (byte) 0xF0,
                (byte) 0x20, (byte) 0x01};
        emvParam.setExCapability(ExCapability);
        byte[] CountryCode = {(byte) 0x01, (byte) 0x56};
        byte[] TransCurrCode = {(byte) 0x01, (byte) 0x56};
        byte[] ReferCurrCode = {(byte) 0x01, (byte) 0x56};
        emvParam.setCountryCode(CountryCode);
        emvParam.setTransCurrCode(TransCurrCode);
        emvParam.setTransCurrExp((byte) 0x02);
        emvParam.setReferCurrCode(CountryCode);
        emvParam.setCL_TransLimit(100000);
        emvParam.setTransType((byte) 0x01);// 交易类型
        byte[] TermTransQuali = {0x24, 0x00, 0x00, (byte) 0x80};
        emvParam.setTermTransQuali(TermTransQuali);
        emvParam.setCL_bStatusCheck((byte) 0x00);
        emvParam.setCL_CVMLimit(10000);
        emvParam.setCL_FloorLimit(20000);
        byte[] params = emvParam.toBytes();
        return financialModule.EmvLib_SetParam(params);

    }

    /**
     * 自动识别卡类型
     */
    public void autoReadCardNo() {

        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            SystemClock.sleep(150);
            if (financialModule.libIccCheck((byte) 0x00) == 0) {
                if (getPan((byte) 0x00)) {
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (getPan((byte) 0x01)) {
                    break;
                }
            }
            SystemClock.sleep(150);
            if (financialModule.libMcrCheck() == 0) {
                if (mcrRead()) {
                    break;
                }
            }
            SystemClock.sleep(150);

        }
        closeModule();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    /**
     * 全部打开
     *
     * @return
     */
    public int openModule() {
        int ret = -1;
        ret = financialModule.libMcrOpen();
        SystemClock.sleep(50);
//        if(ret!=0)
//            return ret;
        byte[] atr = new byte[20];
        ret = financialModule.libIccOpen((byte) 0, (byte) 1, atr);
        SystemClock.sleep(50);
//        if(ret!=0)
//            return ret;
        ret = financialModule.libPiccOpen();

        return 0;
    }

    /**
     * 全部关闭
     */
    public void closeModule() {

        financialModule.libMcrClose();
        financialModule.libIccClose((byte) 0x00);
        financialModule.libPiccClose();
    }

    /**
     * 打开非接
     *
     * @return
     */
    private Timer openPicc() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        byte[] atr = new byte[20];
        for (int i = 0; i < 3; i++) {
            res = financialModule.libPiccOpen();
            if (res == 0) {
                break;
            } else {
                financialModule.libPiccClose();
            }
        }
        Log.e(TAG, "libPiccOpen:" + res);
        if (res != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.OPEN_ERR);
            bundle.putString("message", "OPEN_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return null;
        }
        return tm;
    }

    /**
     * 打开ic
     *
     * @return
     */
    private Timer openIc() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        byte[] atr = new byte[20];
        for (int i = 0; i < 3; i++) {
            res = financialModule.libIccOpen((byte) 0, (byte) 1, atr);
            if (res == 0) {
                break;
            } else {
                financialModule.libIccClose((byte) 0x00);
            }
        }
        Log.e(TAG, "libIccOpen:" + res);
        return tm;
    }

    /**
     * 打开磁头
     *
     * @return
     */
    private Timer openMsr() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        for (int i = 0; i < 3; i++) {
            res = financialModule.libMcrOpen();
            if (res == 0) {
                break;
            } else {
                financialModule.libMcrClose();
            }
        }
        Log.e(TAG, "LibMcrOpen:" + res);
        if (res != 0) {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.OPEN_ERR);
            bundle.putString("message", "OPEN_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return null;
        }
        return tm;

    }

    public void readPiccCardNo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (getPan((byte) 0x01)) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        financialModule.libPiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    public void readIcCardNo() {
        Timer tm = openIc();
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            if (financialModule.libIccCheck((byte) 0x00) == 0) {
                if (getPan((byte) 0x00)) {
                    break;
                }

            }
            SystemClock.sleep(500);
        }
        financialModule.libIccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 获取主张号（卡号）
     *
     * @param cardType
     * @return
     */
    public boolean getPan(byte cardType) {
//        if (financialModule.EmvLib_Init() != 0) {
//            Bundle bundle = new Bundle();
//            bundle.putInt("code", ErrorDefine.EMV_INIT_ERR);
//            bundle.putString("message", "EmvLib_Init error!");
//            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
//            return false;
//        }
        byte[] pan = new byte[30];
        int[] len = new int[1];
        if (financialModule.EmvLib_GetPan(cardType, pan, len) == 0) {
            BankCardInfoBean bean = new BankCardInfoBean();
            if (cardType == (byte) 0x00) {
                bean.setCardType(0);
            } else {
                bean.setCardType(2);
            }
            bean.setCardNo(new String(pan, 0, len[0]));
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.GET_PAN_ERR);
            bundle.putString("message", "GET_PAN_ERR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return false;
        }

    }


    public void readMsr() {
        Timer tm = openMsr();
        if (tm == null) {
            return;
        }
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    Bundle bundle = new Bundle();
                    bundle.putInt("code", ErrorDefine.TIME_OUT);
                    bundle.putString("message", "Time out!");
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                    break;
                }
            }
            if (financialModule.libMcrCheck() == 0) {

                if (mcrRead()) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        financialModule.libMcrClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public boolean mcrRead() {
        byte[] track1 = new byte[255];
        byte[] track2 = new byte[255];
        byte[] track3 = new byte[255];
        int result = financialModule.libMcrRead(track1, track2, track3);
        if (result != 0) {
            String tk1 = ByteTool.bytesToString(track1);
            String tk2 = ByteTool.bytesToString(track2);
            String tk3 = ByteTool.bytesToString(track3);
            Log.e(TAG, "tk1:" + tk1 + "--tk2:" + tk2 + "--tk3:" + tk3);
            BankCardInfoBean bean = new BankCardInfoBean();
            bean.cardType = 1;
            String cardno = "";
            if(tk2!= null && tk2.length()>0){
                cardno = decodeCardNo(tk2);
            }
            if(cardno==null){
                Bundle bundle = new Bundle();
                bundle.putInt("code", ErrorDefine.SWIPE_ERROR);
                bundle.putString("message", "SWIPE_ERROR!");
                deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                return false;
            }
            bean.setCardNo(cardno);
            bean.track1Data = tk1.trim();
            bean.track2Data = tk2.trim();
            bean.track3Data = tk3.trim();
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            Bundle bundle = new Bundle();
            bundle.putInt("code", ErrorDefine.SWIPE_ERROR);
            bundle.putString("message", "SWIPE_ERROR!");
            deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            return false;
        }

    }

    /**
     * 从二磁道取卡号
     *
     * @param track
     * @return
     */
    public static String decodeCardNo(String track) {
        int start = 0;
        if (track != null && track.trim().length() > 0) {
            int track2_end = track.indexOf("=");
            for (int i = 0; i < track.length(); i++) {
                if (Character.isDigit(track.charAt(i))) {
                    start = i;
                    break;
                }
            }
            String cardNo = track.substring(start, track2_end);
            return cardNo;
        }
        return null;
    }

    /**
     * 从tag57取卡号
     *
     * @param track2
     * @return
     */
    public static String getCardNo(String track2) {
        if (track2 == null)
            return null;
        int sta = 0;
        int end = track2.indexOf("D");
        if (end != -1) {
            String cardno = track2.substring(sta, end);
            return cardno;
        }
        return null;
    }

    /**
     * 生成记录
     *
     * @param log
     * @return
     */
    public static List<TradeLogBean> parseLog(byte[] log) {
        int num = log[0];
        Log.e("num", num + "===");
        List<TradeLogBean> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            try {
                TradeLogBean bean = new TradeLogBean();
                byte[] tmp = new byte[6];
                System.arraycopy(log, 1 + i * 45, tmp, 0, 6);
                bean.setAmount(ByteTool.byte2hex(tmp));
                System.arraycopy(log, 1 + 6 + i * 45, tmp, 0, 6);
                bean.setOtherAmount(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + i * 45, tmp, 0, 2);
                bean.setTransNo(ByteTool.byteArray2int(tmp));
                tmp = new byte[1];
                System.arraycopy(log, 1 + 6 + 6 + 2 + i * 45, tmp, 0, 1);
                bean.setTransType(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + i * 45, tmp, 0, 2);
                bean.setCountryCode(ByteTool.byte2hex(tmp));

                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + i * 45, tmp, 0, 2);
                bean.setTransCurrCode(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + i * 45, tmp, 0, 3);
                bean.setDate(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + i * 45, tmp, 0, 3);
                bean.setTime(ByteTool.byte2hex(tmp));
                tmp = new byte[20];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + 3 + i * 45, tmp, 0, 20);
                try {
                    bean.setMerchName(new String(tmp, "gbk").trim());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                list.add(bean);
            } catch (ArrayIndexOutOfBoundsException e) {
                break;
            }

        }
        return list;

    }

    protected static void deliverResult(final DeviceCallback callback, DeviceInterface.Result result, Bundle bundle, boolean onMainThread) {

        DeviceInterface.deliverResult(callback, result, bundle, onMainThread);

    }


}
